package cn.slg.module.system.service.pk.skill;

import cn.slg.module.system.dal.dataobject.state.PersistenceState;
import cn.slg.module.system.dal.dataobject.state.PropertyState;
import cn.slg.module.system.dal.dataobject.wujiang.WuJiangDO;
import cn.slg.module.system.service.pk.utils.Random;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Consumer;

import static cn.slg.module.system.service.pk.skill.AllSkill.allSkillFunc;
import static cn.slg.module.system.service.pk.utils.Collection.exceptSelf;
import static cn.slg.module.system.service.pk.utils.Harm.skillHarmCount;
import static cn.slg.module.system.service.pk.utils.PrepareSkill.whetherContain;
import static cn.slg.module.system.service.pk.utils.Random.random;
import static cn.slg.module.system.service.pk.utils.Show.*;
import static cn.slg.module.system.service.pk.utils.Target.randomTargets;

// 存放着所有的主动战法
public class InitiativeSkill {


    static {
        try {
            // 通过反射，拿到类对象
            Class<?> aClass = InitiativeSkill.class;

            // 拿到类对象所有声明的方法
            // getDeclaredMethods 能拿到所有的动态代理方法，而这些动态代理方法是private的，所以不能直接访问。
            // 因此，在这里用 getMethods() 拿到所有的方法，再只要静态方法
            Method[] methods = aClass.getMethods();

            // 遍历，只要静态方法
            for (Method method : methods) {
                if (Modifier.isStatic(method.getModifiers())) {
                    // 拿到类对象的静态方法
                    allSkillFunc.put(method.getName(), aClass.getMethod(method.getName(), Method.class, WuJiangDO.class, String.class, Byte.class, byte.class));
                }
            }
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }




    // 主动_机略纵横
    // 发动概率：1级:45% 10级:45%
    // 准备1回合，对敌军群体(2人)造成灼烧、中毒状态，每回合持续造成伤害（伤害率29%→58%，受智力影响），持2回合
    // 就是准备1回合，下一回合轮到该武将，就发动，持续性状态，只有在被施加武将行动时，才触发效果。
    // 技能面板伤害计算公式：y = 0.0322 * 技能等级 + 0.2578
    public static void jiLueZongHeng(Method skill, WuJiangDO attacker, String skillName, Byte skillLevel, byte roundNumber) {
        // 准备战法处理机制
        boolean contain = whetherContain(attacker, skillName, 0.45f);

        // 如果已经包含该准备战法，那就直接发动
        if (contain) {
            // 显示: [武将名]发动战法[战法名]
            skillNameShow(attacker, skillName);

            // 伤害除了技能面板，还受到智力影响
            Float harmRate = (float) (0.0322 * skillLevel + 0.2578);

            // 确定技能施加的目标和个数
            // 先确定可选目标
            List<WuJiangDO> confirmChoiceRange = attacker.confirmChoiceRange(false);
            // 再基于技能效果,选中目标,
            List<WuJiangDO> targets = randomTargets(confirmChoiceRange, 2);

            // 为每个目标依次挂上状态
            targets.forEach(target -> {
                // 先看能否命中目标
                boolean whetherHitTarget = attacker.whetherHitTarget(target);
                if (whetherHitTarget) {
                    // 持续性状态，施加时不会造成伤害
                    boolean canAdd = PersistenceState.canAddState("灼烧", attacker, target, skillName, (byte) 2);
                    if (canAdd) {
                        PersistenceState.addState(true, false, true, "灼烧", attacker, target, skill, skillName, (byte) 2, harmRate);
                    }
                    canAdd = PersistenceState.canAddState("中毒", attacker, target, skillName, (byte) 2);
                    if (canAdd) {
                        PersistenceState.addState(true, false, true, "中毒", attacker, target, skill, skillName, (byte) 2, harmRate);
                    }


                }
            });

        }
    }


    // 主动_骁勇善战
    // 发动概率: 1级:35% 10级:35%
    // 准备1回合，对敌军单体造成一次兵刃攻击（伤害率150%→300%)并提高自己20→40点速度，持续2回合
    // 造成一次兵刃攻击 y = 0.1667 * 技能等级 + 1.3333
    // 提高速度        y = 2.2222 * 技能等级 + 17.778
    public static void xiaoYongShanZhan(Method skill, WuJiangDO attacker, String skillName, Byte skillLevel, byte roundNumber) {
        // 准备战法处理机制
        boolean contain = whetherContain(attacker, skillName, 0.35f);

        // 如果已经包含该准备战法，那就直接发动
        if (contain) {
            // 显示: [武将名]发动战法[战法名]
            skillNameShow(attacker, skillName);

            // 确定技能效果率
            Float physicalHarmRate = (float) (0.1667 * skillLevel + 1.3333);
            Float increasePvSuDu = (float) (2.2222 * skillLevel + 17.778);

            // 确定技能施加的目标和个数
            // 先确定可选目标
            List<WuJiangDO> confirmChoiceRange = attacker.confirmChoiceRange(false);
            // 再基于技能效果,选中目标,
            WuJiangDO target = randomTargets(confirmChoiceRange, 1).getFirst();

            // 先看能否命中目标
            boolean whetherHitTarget = attacker.whetherHitTarget(target);
            if (whetherHitTarget) {

                // harm>=0，非null，返回伤害值。
                Short harm = attacker.whenCalculateHarm(true, attacker, target, attacker::getPvWuLi, target::getPvTongShuai, physicalHarmRate);

                // 累计 攻击者 战法杀伤(上面已经计算好此次攻击的伤害值了，无论目标死没死，这都要先统计)
                skillHarmCount(attacker, skillName, harm);

                // 先处理受攻击者，并显示信息(返回是否战斗结束)
                boolean isEnd = target.whenIsSkillAttack(attacker, skillName, harm);
                if (!isEnd) {
                    // 如果没有结束战斗，攻击者执行。。。
                    attacker.whenSkillPhysicalAttack(target, harm);
                    // 给自己施加状态
                    boolean canAdd = PropertyState.canAddState("提高速度", attacker, attacker, skill, skillName, (byte) 2);
                    if (canAdd) {
                        Consumer<WuJiangDO> begin = wuJiangDO -> {
                            wuJiangDO.setPvSuDu(wuJiangDO.getPvSuDu() + increasePvSuDu);
                            // 生效时显示
                            propertyStateShow(wuJiangDO, "提高速度", false, increasePvSuDu, wuJiangDO::getPvSuDu);
                        };

                        Consumer<WuJiangDO> end = wuJiangDO -> {
                            wuJiangDO.setPvSuDu(wuJiangDO.getPvSuDu() - increasePvSuDu);
                        };
                        // 添加该状态
                        PropertyState.addState(false, "提高速度", attacker, attacker, skill, skillName, (byte) 2, begin, end);
                    }
                }
            }
        }
    }


    // 主动_进言
    // 发动概率: 1级:35% 10级:35%
    // 使友军单体主动战法发动几率提高4%→8%，并提高20→40点智力，持续2回合
    // 发动主动战法几率 y = 0.0044 * 等级 + 0.0356
    // 提高智力        y = 2.2222 * 等级 + 17.778
    public static void jinYan(Method skill, WuJiangDO attacker, String skillName, Byte skillLevel, byte roundNumber) {
        // 基于发动概率,判断是否能够发动
        boolean skillProbability = cn.slg.module.system.service.pk.utils.Random.probability(0.35f + attacker.getInitiativeSkillRate());
        if (skillProbability) {
            // 显示: [武将名]发动战法[战法名]
            skillNameShow(attacker, skillName);

            // 确定技能效果率
            Float increaseInitiativeRate = (float) (0.0044 * skillLevel + 0.0356);
            Float increasePvZhiLi = (float) (2.2222 * skillLevel + 17.778);

            // 确定技能施加的目标和个数
            // 先确定可选目标
            List<WuJiangDO> confirmChoiceRange = attacker.confirmChoiceRange(true);
            List<WuJiangDO> selectableTargets = exceptSelf(confirmChoiceRange, attacker);
            // 如果友军都战死了，就剩自己这个主将了，selectableTargets就是个空List，没有元素，所以要判断。
            if (selectableTargets.size() > 0) {

                // 再基于技能效果,选中目标,
                List<WuJiangDO> targets = randomTargets(selectableTargets, 1);

                for (WuJiangDO target : targets) {
                    // 先看能否命中目标
                    boolean whetherHitTarget = attacker.whetherHitTarget(target);
                    if (whetherHitTarget) {
                        boolean canAdd = PropertyState.canAddState("提高主动战法发动几率", attacker, target, skill, skillName, (byte) 2);
                        if (canAdd) {
                            Consumer<WuJiangDO> begin = wuJiangDO -> {
                                wuJiangDO.setInitiativeSkillRate(wuJiangDO.getInitiativeSkillRate() + increaseInitiativeRate);
                                // 生效时显示
                                propertyStateShow(wuJiangDO, "提高主动战法发动几率", true, increaseInitiativeRate, wuJiangDO::getInitiativeSkillRate);
                            };

                            Consumer<WuJiangDO> end = wuJiangDO -> {
                                wuJiangDO.setInitiativeSkillRate(wuJiangDO.getInitiativeSkillRate() - increaseInitiativeRate);
                            };

                            // 添加该状态
                            PropertyState.addState(false, "提高主动战法发动几率", attacker, target, skill, skillName, (byte) 2, begin, end);
                        }
                        canAdd = PropertyState.canAddState("提高智力", attacker, target, skill, skillName, (byte) 2);
                        if (canAdd) {
                            Consumer<WuJiangDO> begin = wuJiangDO -> {
                                wuJiangDO.setPvZhiLi(wuJiangDO.getPvZhiLi() + increasePvZhiLi);
                                // 生效时显示
                                propertyStateShow(wuJiangDO, "提高智力", false, increasePvZhiLi, wuJiangDO::getPvZhiLi);
                            };

                            Consumer<WuJiangDO> end = wuJiangDO -> {
                                wuJiangDO.setPvZhiLi(wuJiangDO.getPvZhiLi() - increasePvZhiLi);
                            };
                            // 添加该状态
                            PropertyState.addState(false, "提高智力", attacker, target, skill, skillName, (byte) 2, begin, end);
                        }
                    }
                }
            }
        }
    }


    // 主动_谦让:
    // 发动概率: 1级:40% 10级:40%
    // 使我军单体受到的兵刃伤害和谋略伤害降低11%→22%（受智力影响)，持续3回合
    // y = 0.0122 * 等级 + 0.0978
    public static void qianRang(Method skill, WuJiangDO attacker, String skillName, Byte skillLevel, byte roundNumber) {
        // 基于发动概率,判断是否能够发动
        boolean skillProbability = cn.slg.module.system.service.pk.utils.Random.probability(0.4f + attacker.getInitiativeSkillRate());
        if (skillProbability) {
            // 显示: [武将名]发动战法[战法名]
            skillNameShow(attacker, skillName);

            // 确定技能效果率
            Float effectRate = (float) (0.0122 * skillLevel + 0.0978);

            // 确定技能施加的目标和个数
            // 先确定可选目标
            List<WuJiangDO> confirmChoiceRange = attacker.confirmChoiceRange(true);

            List<WuJiangDO> selectableTargets = exceptSelf(confirmChoiceRange, attacker);

            // 再基于技能效果,选中目标,
            if (selectableTargets.size() > 0) {
                List<WuJiangDO> targets = randomTargets(selectableTargets, 1);

                for (WuJiangDO target : targets) {
                    // 施加状态
                    boolean canAdd = PropertyState.canAddState("受到伤害降低", attacker, target, skill, skillName, (byte) 3);
                    if (canAdd) {
                        Consumer<WuJiangDO> begin = wuJiangDO -> {
                            wuJiangDO.setIsPhysicalHarmRate(wuJiangDO.getIsPhysicalHarmRate() * (1 - effectRate));
                            wuJiangDO.setIsMagicHarmRate(wuJiangDO.getIsMagicHarmRate() * (1 - effectRate));
                            // 生效时显示
                            propertyStateShow(wuJiangDO, "受到的谋略伤害降低了", true, effectRate, wuJiangDO::getIsMagicHarmRate);
                            propertyStateShow(wuJiangDO, "受到的兵刃伤害降低了", true, effectRate, wuJiangDO::getIsPhysicalHarmRate);
                        };

                        Consumer<WuJiangDO> end = wuJiangDO -> {
                            // 状态被取消时操作
                            wuJiangDO.setIsPhysicalHarmRate(wuJiangDO.getIsPhysicalHarmRate() / (1 - effectRate));
                            wuJiangDO.setIsMagicHarmRate(wuJiangDO.getIsMagicHarmRate() / (1 - effectRate));
                        };

                        // 添加该状态
                        PropertyState.addState(false, "受到伤害降低", attacker, target, skill, skillName, (byte) 3, begin, end);
                    }
                }
            }
        }
    }


    // 主动_轻勇飞燕：
    // 发动概率: 1级:40% 10级:40%
    // 对敌军单体发动兵刃攻击（伤害率42%→84%)，随机释放2-4次。
    // 伤害率 = 0.0467 * 技能等级 + 0.3733
    public static void qingYongFeiYan(Method skill, WuJiangDO attacker, String skillName, Byte skillLevel, byte roundNumber) {

        // 基于发动概率,判断是否能够发动
        boolean skillProbability = cn.slg.module.system.service.pk.utils.Random.probability(0.4f + attacker.getInitiativeSkillRate());
        if (skillProbability) {
            // 显示: [武将名]发动战法[战法名]
            skillNameShow(attacker, skillName);

            // 确定技能伤害率
            Float harmRate = (float) (0.0467 * skillLevel + 0.3733);

            // 确定释放次数，每次独立判定目标
            int fre = random.nextInt(2, 5);

            // 能触发多次伤害的技能，要考虑中间敌军战死，主将战死，战斗结束问题。由于触发效果，导致自己无法继续行动等问题
            boolean isEnd = false;
            for (int i = 0; i < fre; i++) {
                if (attacker.canSkillAttack() && attacker.canNormalAttack()) {
                    // 确定技能施加的目标和个数
                    // 可选目标范围
                    List<WuJiangDO> confirmChoiceRange = attacker.confirmChoiceRange(false);

                    // 再基于技能效果,选中目标,
                    List<WuJiangDO> targets = randomTargets(confirmChoiceRange, 1);

                    // 针对目标依次发动攻击
                    for (WuJiangDO target : targets) {
                        // 先看能否命中目标
                        boolean whetherHitTarget = attacker.whetherHitTarget(target);
                        if (whetherHitTarget) {

                            // harm>=0，非null，返回伤害值。
                            Short harm = attacker.whenCalculateHarm(true, attacker, target, attacker::getPvWuLi, target::getPvTongShuai, harmRate);
                            // 累计 攻击者 战法杀伤(上面已经计算好此次攻击的伤害值了，无论目标死没死，这都要先统计)
                            skillHarmCount(attacker, skillName, harm);

                            // 先处理受攻击者(返回是否战斗结束)
                            isEnd = target.whenIsSkillAttack(attacker, skillName, harm);

                            if (!isEnd) {
                                // 如果没有结束战斗，攻击者执行。。。
                                attacker.whenSkillPhysicalAttack(target, harm);
                            } else {
                                // 结束战斗，不用对下一个目标继续发动技能攻击，也不用继续触发多段伤害了。
                                break;
                            }
                        }
                    }
                    if (isEnd) {
                        break;
                    }
                }
            }
        }

    }

    // 主动_避实击虚：
    // 发动概率: 1级:50% 10级:50%
    // 对统率最低的敌军单体发动一次兵刃攻击（伤害率92.5%→185%)
    // 伤害率 = 0.1028 * 技能等级 + 0.8222
    public static void biShiJiXu(Method skill, WuJiangDO attacker, String skillName, Byte skillLevel, byte roundNumber) {

        if (true) {
            if (true) {
                // 再基于发动概率,判断是否能够发动
                boolean skillProbability = Random.probability(0.5f + attacker.getInitiativeSkillRate());

                if (skillProbability) {
                    // 显示: [武将名]发动战法[战法名]
                    skillNameShow(attacker, skillName);

                    // 确定技能伤害率
                    Float harmRate = (float) (0.1028 * skillLevel + 0.8222);

                    // 确定技能施加的目标和个数
                    // 可选目标范围
                    List<WuJiangDO> confirmChoiceRange = attacker.confirmChoiceRange(false);

                    // 再基于技能效果,选中目标,单体还是群体考虑下
                    WuJiangDO target = confirmChoiceRange.stream().min(Comparator.comparing(wuJiangDO -> wuJiangDO.getPvTongShuai())).get();

                    // 遍历每一个目标
                    // 先看能否命中目标
                    boolean whetherHitTarget = attacker.whetherHitTarget(target);

                    if (whetherHitTarget) {
                        // 如果命中目标

                        // harm>=0，非null，返回伤害值。
                        Short harm = attacker.whenCalculateHarm(true, attacker, target, attacker::getPvWuLi, target::getPvTongShuai, harmRate);

                        // 累计 攻击者 战法杀伤(上面已经计算好此次攻击的伤害值了，无论目标死没死，这都要先统计)
                        skillHarmCount(attacker, skillName, harm);

                        // 先处理受攻击者(返回是否战斗结束)
                        boolean isEnd = target.whenIsSkillAttack(attacker, skillName, harm);

                        // 战斗是否结束了
                        if (!isEnd) {
                            // 如果没有结束战斗，攻击者执行。。。
                            attacker.whenSkillPhysicalAttack(target, harm);
                        } else {
                            // 4.如果要结束战斗,就不触发攻击者的各种效果，也不继续针对下一个目标发动攻击了
                        }
                    } else {
                        // 如果没有命中目标

                    }

                }
            }
        }
    }

    // 群攻技能基础模板
    // public static void biShiJiXu(WuJiangDO self, String skillName, Byte skillLevel) {
    //     // 先确定技能施加的目标和个数
    //     Supplier<Target> targetSupplier = () -> {
    //         List<WuJiangDO> targets = self.getEnemy().getFightGroup();
    //         return new Target(targets, 1);
    //     };
    //
    //     // 拿到要攻击的对象
    //     List<WuJiangDO> targets = Target.confirmTarget(targetSupplier);
    //
    //     // 再确定技能伤害率
    //     Float harmRate = (float) (0.1028 * skillLevel + 0.8222);
    //
    //     // 依次针对每个目标发动攻击
    //     targets.forEach(target -> {
    //         // 此次攻击能够造成的伤害
    //         Short harm = Harm.harm(self, target, self::getPvWuLi, target::getPvTongShuai, harmRate);
    //
    //         //
    //
    //         // 扣除目标的兵力
    //         target.setBingLi((short) (target.getBingLi() - harm));
    //
    //         String str1 = "   " + self.getBingZhong() + "  [" + self.getUserId().toString() + "+" + self.getName() + "]" +
    //                 "发动战法" + "【" + skillName + "】" + "\n";
    //         formatStringPrint(str1, 29, 0);
    //
    //         // String formatBlank = String.format("%" + (str1.indexOf("]对") + 3) + "s", "");
    //         // formatStringPrint(formatBlank + "[" + target.userId.toString() + "+" + target.name + "]"
    //         //         + "损失了兵力" + harm + "(" + target.bingLi + ")"
    //         //         + "\n", 29, 0);
    //     });
    //
    //
    // }


}

